import api from '../../api';
import { formatDate, uuid } from '../index';
import store from '@/utils/store';
/**
 * 异常日志捕获工具
 */
class ErrorLogger {
    constructor() {
        // 初始化配置
        this.config = {
            debug: import.meta.env.VITE_DEGGER_LOG // 调试模式
        };

        // 初始化标记
        this.initialized = false;
    }

    /**
     * 初始化日志系统
     * @param {Object} options 配置选项
     */
    init(options = {}) {
        if (this.initialized) return;

        // 合并配置
        Object.assign(this.config, options);

        // 初始化事件监听
        this.setupEventListeners();

        this.initialized = true;
        this.logger('logger init');
    }

    /**
     * 设置各类事件监听
     */
    setupEventListeners() {
        // 捕获JS执行错误
        window.addEventListener(
            'error',
            (event) => {
                if (
                    event.target instanceof HTMLScriptElement ||
                    event.target instanceof HTMLLinkElement ||
                    event.target instanceof HTMLImageElement ||
                    event.target instanceof HTMLVideoElement ||
                    event.target instanceof HTMLAudioElement
                ) {
                    // 资源加载错误
                    this.captureResourceError(event);
                } else {
                    // JS错误
                    this.captureJsError(event);
                }
            },
            true
        );

        // 捕获未处理的Promise异常
        window.addEventListener('unhandledrejection', (event) => {
            this.capturePromiseError(event);
            event.preventDefault();
        });

        // 捕获iframe错误
        window.addEventListener(
            'message',
            (event) => {
                if (event.data && event.data.type === 'iframeError') {
                    this.captureIframeError(event.data.error);
                }
            },
            false
        );
    }

    /**
     * 捕获JS执行错误
     * @param {ErrorEvent} event 错误事件
     */
    captureJsError(event) {
        const errorInfo = {
            type: 'js_error',
            message: event.message || 'Unknown error',
            stack: event.stack || '',
            filename: event.filename || window.location.href,
            lineno: event.lineno,
            colno: event.colno
        };

        this.reportErrorInfo(errorInfo);
    }

    /**
     * 捕获资源加载错误
     * @param {ErrorEvent} event 错误事件
     */
    captureResourceError(event) {
        const target = event.target;
        const errorInfo = {
            type: 'resource_error',
            message: `Resource load failed: ${target.tagName}`,
            url: target.src || target.href,
            tagName: target.tagName,
            status:
                target.naturalWidth === 0 && target.tagName === 'IMG' ? 'load_failed' : 'unknown'
        };

        this.reportErrorInfo(errorInfo);
    }

    /**
     * 捕获Promise未处理异常
     * @param {PromiseRejectionEvent} event 拒绝事件
     */
    capturePromiseError(event) {
        const reason = event.reason;
        const errorInfo = {
            type: 'promise_error',
            message: reason?.message || 'Unhandled promise rejection',
            stack: reason?.stack || '',
            reason: reason?.toString() || ''
        };

        this.reportErrorInfo(errorInfo);
    }

    /**
     * 捕获iframe错误
     * @param {Object} error 错误信息
     */
    captureIframeError(error) {
        const errorInfo = {
            type: 'iframe_error',
            message: error.message || 'Iframe error occurred',
            stack: error.stack || '',
            iframeUrl: error.url || ''
        };

        this.reportErrorInfo(errorInfo);
    }

    /**
     * 组装完整错误信息并加入队列
     * @param {Object} errorInfo 错误基本信息
     * @param {Object} options 自定义数据
     */
    async reportErrorInfo(errorInfo, options = {}) {
        // 组装完整日志
        const params = {
            pageId: options.pageId || store.get('PAGE_ID') || '', // 页面ID
            requestId:
                options.requestId || `REQ-${formatDate(new Date(), '{y}{m}{d}')}-${uuid(5, 5)}`, // 请求ID
            clientType: 'WE_CHAT_H5', // 端
            moduleCode: options.moduleCode || '-', // 模块编码
            tag: options.tag || '-', //标签：自定义，方便阅读和查询
            code: options.code || '-', // 代码（没值的-,需要重点关注、监控的，需要指定）
            content: typeof errorInfo === 'string' ? errorInfo : JSON.stringify(errorInfo), // 错误信息
            uri: options.uri, // 前端的页面路径，或后端的接口uri
            businessTime: Date.now(), // 业务时间（发送日志的当前时间）
            takeTime: options.takeTime || '-1', // 耗时（毫秒，无值-1）
            logLevel: options.logLevel || 'info' // 日志等级
        };

        if (this.config.debug) {
            this.logger(params, '=======error=======>', errorInfo);
            return;
        }
        try {
            await api.fetchPost('addLogSingle', params, {
                isLoading: false,
                isLogger: true,
                hasErr: true
            });
        } catch (err) {
            this.logger(params, '=======error=======>', err);
            console.log(err);
        }
    }

    /**
     * 手动上报错误
     * @param {Error} error 错误对象
     * @param {Object} options 自定义数据
     */
    reportError(error, options = {}) {
        if (!(error instanceof Error)) {
            error = new Error(typeof error === 'string' ? error : 'Custom error');
        }

        const errorInfo = {
            type: 'custom_error',
            message: error.message,
            stack: error.stack || '',
            name: error.name
        };

        this.reportErrorInfo(errorInfo, options);
    }

    /**
     * 获取设备信息
     * @returns {Object} 设备信息
     */
    getDeviceInfo() {
        return {
            userAgent: navigator.userAgent,
            browser: this.getBrowserInfo(),
            os: this.getOsInfo(),
            screen: {
                width: window.screen.width,
                height: window.screen.height,
                dpr: window.devicePixelRatio
            },
            language: navigator.language || navigator.userLanguage,
            timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
            network: this.getNetworkInfo()
        };
    }

    /**
     * 获取浏览器信息
     * @returns {Object} 浏览器信息
     */
    getBrowserInfo() {
        const userAgent = navigator.userAgent;
        let browser = { name: 'Unknown', version: 'Unknown' };

        if (userAgent.includes('Chrome')) {
            browser.name = 'Chrome';
            browser.version = userAgent.match(/Chrome\/(\d+\.\d+)/)[1];
        } else if (userAgent.includes('Firefox')) {
            browser.name = 'Firefox';
            browser.version = userAgent.match(/Firefox\/(\d+\.\d+)/)[1];
        } else if (userAgent.includes('Safari') && !userAgent.includes('Chrome')) {
            browser.name = 'Safari';
            browser.version = userAgent.match(/Version\/(\d+\.\d+)/)[1];
        } else if (userAgent.includes('Edge')) {
            browser.name = 'Edge';
            browser.version = userAgent.match(/Edge\/(\d+\.\d+)/)[1];
        } else if (userAgent.includes('MSIE') || userAgent.includes('Trident/')) {
            browser.name = 'IE';
            browser.version =
                userAgent.match(/(MSIE \d+\.\d+|Trident\/.*?rv:(\d+\.\d+))/)[2] || '11';
        }

        return browser;
    }

    /**
     * 获取操作系统信息
     * @returns {Object} 操作系统信息
     */
    getOsInfo() {
        const userAgent = navigator.userAgent;
        let os = { name: 'Unknown', version: 'Unknown' };

        if (userAgent.includes('Windows')) {
            os.name = 'Windows';
            if (userAgent.includes('Windows NT 10.0')) os.version = '10/11';
            else if (userAgent.includes('Windows NT 6.3')) os.version = '8.1';
            else if (userAgent.includes('Windows NT 6.2')) os.version = '8';
            else if (userAgent.includes('Windows NT 6.1')) os.version = '7';
        } else if (userAgent.includes('Mac OS X')) {
            os.name = 'macOS';
            os.version = userAgent.match(/Mac OS X (\d+_\d+)/)[1].replace(/_/g, '.');
        } else if (userAgent.includes('Android')) {
            os.name = 'Android';
            os.version = userAgent.match(/Android (\d+\.\d+)/)[1];
        } else if (userAgent.includes('iOS')) {
            os.name = 'iOS';
            os.version = userAgent.match(/iOS (\d+\.\d+)/)[1];
        } else if (userAgent.includes('Linux')) {
            os.name = 'Linux';
        }

        return os;
    }

    /**
     * 获取网络信息
     * @returns {Object|null} 网络信息
     */
    getNetworkInfo() {
        if (!navigator.connection) return null;

        return {
            type: navigator.connection.type,
            effectiveType: navigator.connection.effectiveType,
            downlink: navigator.connection.downlink,
            rtt: navigator.connection.rtt
        };
    }

    /**
     * 获取页面信息
     * @returns {Object} 页面信息
     */
    getPageInfo() {
        return {
            url: window.location.href,
            path: window.location.pathname,
            hash: window.location.hash,
            search: window.location.search,
            referrer: document.referrer,
            title: document.title,
            stayTime: Date.now() - this.pageStartTime,
            scrollPosition: {
                x: window.scrollX,
                y: window.scrollY
            }
        };
    }

    /**
     * 调试日志
     * @param  {...any} args 日志参数
     */
    logger(...args) {
        console.log('=======logger======>', ...args);
    }

    //调试
    debug(erronInfo, option) {
        this.reportError(erronInfo, { ...option, logLevel: 'debug' });
    }
    // info
    info(erronInfo, option) {
        this.reportError(erronInfo, { ...option, logLevel: 'info' });
    }
    // 警告
    warn(erronInfo, option) {
        this.reportError(erronInfo, { ...option, logLevel: 'warn' });
    }
    // 错误
    error(erronInfo, option) {
        this.reportError(erronInfo, { ...option, logLevel: 'error' });
    }
}

// 实例化并导出
const errorLogger = new ErrorLogger();

// 暴露全局方法
window.errorLogger = errorLogger;
window.reportError = (error, customData) => {
    errorLogger.reportError(error, customData);
};

export default errorLogger;
